package fr.cephb.locustree;

import java.util.Arrays;

import fr.cephb.json.JSONBuilder;
import fr.cephb.json.JSONable;

/**
 * Hold the data of a histogram for LocusTree
 * @author pierre
 *
 */
public class LTHistogram
	implements JSONable
	{
	private static final int DEFAULT_HISTOGRAM_WIDTH=4;
	private int max_histogram_count=0;
	private int histogram_counts[];
	private int chrom_start;
	private int chrom_length;
	private int panel_width;
	
	public LTHistogram(
			int panel_width,
			int chrom_start,
			int chrom_length
			)
		{
		this.panel_width=panel_width;
		this.chrom_start=chrom_start;
		this.chrom_length=chrom_length;
		int nbr_histogram= panel_width/DEFAULT_HISTOGRAM_WIDTH;
		if(nbr_histogram> chrom_length)
			{
			nbr_histogram=chrom_length;
			}
		this.histogram_counts=new int[nbr_histogram];
		
		Arrays.fill(this.histogram_counts,0);
		}
	
	/** returns the number of bars in this histogram */
	public int size()
		{
		return this.histogram_counts.length;
		}
	
	/** get value for the index-th bar */ 
	public int get(int index)
		{
		return this.histogram_counts[index];
		}
	
	/** get value for the index-th bar normalized according to maximum()*/ 
	public double normalized(int index)
		{
		return get(index)/(double)getMaximum();
		}
	
	/** max value found for this historgram */
	public int getMaximum()
		{
		return this.max_histogram_count;
		}
	
	/** returns the number of base as int foreach bar. garanteed to be &gt;= than 1 */
	public int getResolution()
		{
		return Math.max((int)getBasesPerHistogram(), 1);
		}
	
	/** return the width of the whole histogram */
	public int getWidth()
		{
		return this.panel_width;
		}
	
	/** return the width of one bar in pixel . garanteed to be &gt;= than 1 */
	public int getBarWidth()
		{
		return Math.max(getWidth()/size(), 1);
		}
	
	public float getBasesPerHistogram()
		{
		return getChromLength()/(float)size();
		}
	
	public int getChromStart()
		{
		return this.chrom_start;
		}
	
	public int getChromLength()
		{
		return this.chrom_length;
		}
	
	public int getChromEnd()
		{
		return getChromStart()+getChromLength();
		}
	
	public void seen(LTNode root)
		{
		float base_per_histo= getBasesPerHistogram();
		float base_index= getChromStart();
		for(int i=0;i< this.histogram_counts.length;++i)
			{
			if(base_index + base_per_histo < root.getStart())
				{
				base_index+=base_per_histo;
				continue;
				}
			if(base_index >= root.getEnd()) break;
			this.histogram_counts[i]+=root.getCountEntitiesBelow();
			this.max_histogram_count=Math.max(this.max_histogram_count, this.histogram_counts[i]);
			base_index+=base_per_histo;
			}
		}
	
	
	@Override
	public int hashCode()
		{
		final int prime = 31;
		int result = 1;
		result = prime * result + chrom_length;
		result = prime * result + chrom_start;
		return result;
		}

	@Override
	public boolean equals(Object obj)
		{
		return (this == obj);
		}

	@Override
	public String toJSON()
		{
		return new JSONBuilder().
			put("start", getChromStart()).
			put("end", getChromEnd()).
			put("length", getChromLength()).
			put("max", getMaximum()).
			put("counts", this.histogram_counts).
			getString();
		}
	@Override
	public String toString()
		{
		return toJSON();
		}
	}
